package com.fowo.api.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fowo.api.common.model.ImportRow;
import com.fowo.api.common.model.OptionItem;
import com.fowo.api.entity.AmazonOrderList;
import com.fowo.api.entity.AmazonOrderListProduct;
import com.fowo.api.entity.AmazonSalesStatement;
import com.fowo.api.flow.entity.WorkFlow;
import com.fowo.api.flow.service.WorkFlowService;
import com.fowo.api.mapper.AmazonOrderListMapper;
import com.fowo.api.mapper.AmazonSalesStatementMapper;
import com.fowo.api.mapper.CustomizedSalesStatementMapper;
import com.fowo.api.model.amazon.sales.statement.AmazonSalesStatementImportPo;
import com.fowo.api.model.amazon.sales.statement.AmazonSalesStatementItemVo;
import com.fowo.api.model.amazon.sales.statement.AmazonSalesStatementSearchParamPo;
import com.fowo.api.model.amazon.sales.statement.AmazonSalesStatementVo;
import com.fowo.api.service.CustomizedSalesStatementService;
import com.fowo.api.sys.entity.SysFile;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CustomizedSalesStatementServiceImpl
        extends ServiceImpl<AmazonSalesStatementMapper, AmazonSalesStatement>
        implements CustomizedSalesStatementService {

    /**
     * 引用字段排序字段名转换信息
     */
    public static final Map<String, String> SORT_FIELD_MAP = new HashMap<>() {
        {
            put("countryName", "sa.`name`");
        }
    };

    @Resource
    private AmazonOrderListMapper amazonOrderListMapper;
    @Resource
    protected WorkFlowService workFlowService;
    @Resource
    private CustomizedSalesStatementMapper salesStatementMapper;

    @Override
    public List<AmazonSalesStatementItemVo> asinSales(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    //TODO 待开发
    @Override
    public Page<AmazonSalesStatementItemVo> asinSalesPage(
            AmazonSalesStatementSearchParamPo search
    ) {
        String dimension = search.getDimension();
        search.setDimension(null);
        Page<AmazonSalesStatementItemVo> asinSalesPage = new Page<>();
        if (
                Objects.nonNull(search.getWfStatus()) &&
                        StringUtils.hasText(search.getFormName())
        ) {
            List<WorkFlow> workFlowList = workFlowService.queryWfListByStatus(
                    search.getWfStatus(),
                    search.getFormName()
            );
            if (CollectionUtils.isEmpty(workFlowList)) {
                return asinSalesPage;
            }
            List<Long> ids = workFlowList
                    .stream()
                    .map(WorkFlow::getRecordId)
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(ids)) {
                return asinSalesPage;
            }
            search.setSelectedIds(ids);
        }
        search.initSort("t.id desc", "t.", SORT_FIELD_MAP);
        asinSalesPage = this.baseMapper.asinSalesPage(search.toPage(), search);
//        QueryWrapper<AmazonOrderList> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("del_flag",0);
//        queryWrapper.eq("is_mcf_order",0);
//        queryWrapper.isNotNull("asin");
//        List<AmazonOrderList> amazonOrderLists = amazonOrderListMapper.selectList(queryWrapper);
        //获取日期数据
        SimpleDateFormat sim = new SimpleDateFormat("yyyy-MM-dd");
        String createTime = sim.format(search.getCreateTimeStart());
        String endTime = sim.format(search.getCreateTimeEnd());
        List<Date> dates = findDates(search.getCreateTimeStart(), search.getCreateTimeEnd());
        dates = dates.stream().sorted().collect(Collectors.toList());
        for (AmazonSalesStatementItemVo item : asinSalesPage.getRecords()) {
            List<AmazonOrderListProduct> product = salesStatementMapper.getProduct(item.getAsin());
            Map map = new LinkedHashMap();
            int subTotal = 0;
            try {
                //日
                if (dimension != null && dimension.equals("1")) {
                    for (Date date : dates) {
                        String format = sim.format(date);
                        if (product != null && product.size() > 0) {
                            long count = product.stream().filter(x -> sim.format(x.getCreateTime()).equals(format)).count();
                            map.put(format.substring(format.indexOf("-") + 1), count);
                            subTotal = subTotal + (int) count;
                        } else {
                            map.put(format.substring(format.indexOf("-") + 1), 0);
                        }
                    }
//                    map.put("subTotal", subTotal);
//                    BigDecimal bigDecimal = new BigDecimal(subTotal).divide(new BigDecimal(dates.size()));
//                    map.put("meanValue", bigDecimal.setScale(1, BigDecimal.ROUND_DOWN));
                }
                //周
                if (dimension != null && dimension.equals("2")) {
                    //分割日期
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                    LocalDate date = LocalDate.parse(createTime, formatter);
                    LocalDate date1 = LocalDate.parse(endTime, formatter);
                    List<KeyValueForDate> keyValueForDates = parseWeekRange(date, date1);
                    for (KeyValueForDate forDate : keyValueForDates) {
                        Date parse = sim.parse(forDate.getStartDate());
                        Date parse1 = sim.parse(forDate.getEndDate());
                        if (product != null && product.size() > 0) {
                            long count = product.stream().
                                    filter(x -> x.getCreateTime().after(parse) && x.getCreateTime().before(parse1)).count();
                            map.put(forDate.getStartDate() + "~" + forDate.getEndDate(), count);
                            subTotal = subTotal + (int) count;
                        } else {
                            map.put(forDate.getStartDate() + "~" + forDate.getEndDate(), 0);
                        }
                    }
//                    map.put("subTotal", subTotal);
//                    BigDecimal bigDecimal = new BigDecimal(subTotal).divide(new BigDecimal(dates.size()));
//                    map.put("meanValue", bigDecimal.setScale(1, BigDecimal.ROUND_DOWN));
                }
                //月
                if (dimension != null && dimension.equals("3")) {
                    if(product != null && product.size() > 0){
                        Map<String, List<AmazonOrderListProduct>> collect2 = product.stream()
                                .collect(Collectors.groupingBy(x -> DateUtil.format(x.getCreateTime(), "yyyy-MM")));
                        for (Map.Entry<String, List<AmazonOrderListProduct>> listMap : collect2.entrySet()) {
                            long count = listMap.getValue().stream().
                                    filter(x -> x.getCreateTime().after(search.getCreateTimeStart()) && x.getCreateTime().before(search.getCreateTimeEnd()))
                                    .count();
                            map.put(listMap.getKey(), count);
                            subTotal = subTotal + listMap.getValue().size();
                        }
                    }else {
                        YearMonth c = YearMonth.of(Integer.parseInt(createTime.substring(0, 4)), Integer.parseInt(createTime.substring(5, 7)));
                        YearMonth e = YearMonth.of(Integer.parseInt(endTime.substring(0, 4)), Integer.parseInt(endTime.substring(5, 7)));
                        while (c.isBefore(e) || c.equals(e)){
                            map.put(c.toString(), 0);
                            c = c.plusMonths(1);
                        }
                    }

                }
                //年
                if (dimension != null && dimension.equals("4")) {
                }
                map.put("subTotal", subTotal);
                BigDecimal bigDecimal = new BigDecimal(subTotal).divide(new BigDecimal(dates.size()));
                map.put("meanValue", bigDecimal.setScale(1, BigDecimal.ROUND_DOWN));
            } catch (Exception e) {
                e.printStackTrace();
            }
//            item.setDateData(map);
        }

        List<Long> recordIds = asinSalesPage
                .getRecords()
                .stream()
                .map(AmazonSalesStatementItemVo::getId)
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(recordIds)) {
            return asinSalesPage;
        }
        List<WorkFlow> workFlows = workFlowService.queryWfList(
                recordIds,
                Collections.singletonList(search.getFormName())
        );
        if (CollectionUtils.isEmpty(workFlows)) {
            return asinSalesPage;
        }
        Map<Long, Integer> flowMap = workFlows
                .stream()
                .collect(Collectors.toMap(WorkFlow::getRecordId, WorkFlow::getWfStatus));
        asinSalesPage
                .getRecords()
                .stream()
                .forEach(item -> {
                    if (!flowMap.containsKey(item.getId())) {
                        return;
                    }
                    item.setWfStatus(flowMap.get(item.getId()));
                });

        return asinSalesPage;
    }

    /**
     * 获取某段时间内的所有日期
     *
     * @param startDate yyyy-MM-dd
     * @param endDate   yyyy-MM-dd
     * @return yyyy-MM-dd
     */
    public static List<Date> findDates(Date startDate, Date endDate) {
        Calendar cStart = Calendar.getInstance();
        cStart.setTime(startDate);

        List dateList = new ArrayList();
        //加上起始日期
        dateList.add(startDate);
        // 此日期是否在指定日期之后
        while (endDate.after(cStart.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            cStart.add(Calendar.DAY_OF_MONTH, 1);
            // 如果终止日期小于当前日期
            if (endDate.compareTo(cStart.getTime()) < 0) {
                break;
            }
            dateList.add(cStart.getTime());
        }
        return dateList;
    }

    /**
     * 将时间段按星期分割
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static List<KeyValueForDate> parseWeekRange(LocalDate startDate, LocalDate endDate) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        List<KeyValueForDate> list = new ArrayList<>();

        KeyValueForDate dr = null;

        LocalDate stDate = startDate;
        LocalDate enDate = endDate.plusDays(1);

        while (stDate.isBefore(enDate)) {

            int week = stDate.getDayOfWeek().getValue();

            if (dr == null || week == 1) {
                dr = new KeyValueForDate();
                dr.setStartDate(stDate.format(dtf));
            }

            if (week == 7 || stDate.compareTo(endDate) == 0) {
                dr.setEndDate(stDate.format(dtf));
                list.add(dr);
            }

            stDate = stDate.plusDays(1);
        }

        return list;
    }

    public static class KeyValueForDate {
        private String startDate;
        private String endDate;
        private Integer days;

        public String getStartDate() {
            return startDate;
        }

        public void setStartDate(String startDate) {
            this.startDate = startDate;
        }

        public String getEndDate() {
            return endDate;
        }

        public void setEndDate(String endDate) {
            this.endDate = endDate;
        }

        public Integer getDays() {
            return days;
        }

        public void setDays(Integer days) {
            this.days = days;
        }
    }

    @Override
    public Date asinSalesLastUpdateTime(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public List<AmazonSalesStatementItemVo> asinQuantity(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public Page<AmazonSalesStatementItemVo> asinQuantityPage(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public Date asinQuantityLastUpdateTime(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public List<AmazonSalesStatementItemVo> asinValue(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public Page<AmazonSalesStatementItemVo> asinValuePage(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public Date asinValueLastUpdateTime(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public List<AmazonSalesStatementItemVo> parentAsinSales(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public Page<AmazonSalesStatementItemVo> parentAsinSalesPage(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public Date parentAsinSalesLastUpdateTime(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public List<AmazonSalesStatementItemVo> parentAsinQUantity(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public Page<AmazonSalesStatementItemVo> parentAsinQUantityPage(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public Date parentAsinQUantityLastUpdateTime(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public List<AmazonSalesStatementItemVo> parentAsinValue(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public Page<AmazonSalesStatementItemVo> parentAsinValuePage(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

    @Override
    public Date parentAsinValueLastUpdateTime(AmazonSalesStatementSearchParamPo search) {
        return null;
    }

}
